package cn.lixu.user.service.impl;

import cn.lixu.basic.exception.BusinessException;
import cn.lixu.basic.service.impl.BaseServiceImpl;
import cn.lixu.basic.util.Md5Utils;
import cn.lixu.basic.util.StrUtils;
import cn.lixu.basic.constant.RegisterConstant;
import cn.lixu.org.domain.Logininfo;
import cn.lixu.org.mapper.LogininfoMapper;
import cn.lixu.user.domain.User;
import cn.lixu.user.dto.RegisterDto;
import cn.lixu.user.mapper.UserMapper;
import cn.lixu.user.service.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Service
//只读，事务传播机制=SUPPORTS，有我就用，没有事务就不用
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private LogininfoMapper logininfoMapper;

    /**
     * 手机注册业务
     *
     * @param dto
     */
    @Override
    public void phoneRegister(RegisterDto dto) {


        String phone = dto.getPhone();

        String verifyCode = dto.getVerifyCode();

        String password = dto.getPassword();

        String comfirmPassword = dto.getComfirmPassword();

        //1.检验【非空检验】
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("电话不能为空");
        }
        if (StringUtils.isEmpty(verifyCode)) {
            throw new BusinessException("手机验证码不能为空");
        }
        if (StringUtils.isEmpty(password)) {
            throw new BusinessException("密码不能为空");
        }
        if (StringUtils.isEmpty(comfirmPassword)) {
            throw new BusinessException("确认密码不能为空");
        }
        //2.两次密码是否一致
        if (!password.equals(comfirmPassword)) {
            throw new BusinessException("两次密码不一致，请重新输入");
        }
        //3.手机号码校验，是否被注册
        //通过电话号码查询user对象，如果这个对象存在，则说明之前被注册过
        User userPhone = userMapper.loadByPhone(phone);
        if (userPhone != null) {
            throw new BusinessException("您的手机号码已经被注册，请直接登录");
        }
        //4.验证码是否过期redis
        Object obj = redisTemplate.opsForValue().get(phone + RegisterConstant.PHONEREGISTER);
        if (obj == null) {
            throw new BusinessException("您的验证码已经过期，请重新获取");
        }

        //5.校验验证码是否正确
        String redisCode = obj.toString().split(":")[0];
        if (!verifyCode.equalsIgnoreCase(redisCode)) {
            throw new BusinessException("您的验证码输入错误，请重新获取");
        }

        //6.1保存数据  首先保存在logininfo
        //通过dto获取到logininfo对象
        Logininfo logininfo = dto2Logininfo(dto);

        //通过logininfo获取到user对象
        User user = logininfo2User(logininfo);

        logininfoMapper.save(logininfo);

        // 把自增的主键赋值给user对象， 再保存user。
        user.setLogininfo_id(logininfo.getId());

        userMapper.save(user);

    }

    private User logininfo2User(Logininfo logininfo) {

        User user = new User();
        //copy相同字段
        BeanUtils.copyProperties(logininfo, user);

        return user;
    }

    private Logininfo dto2Logininfo(RegisterDto dto) {

        Logininfo logininfo = new Logininfo();

        logininfo.setUsername(dto.getPhone());

        logininfo.setPhone(dto.getPhone());

        logininfo.setType(1);
        //生成盐值
        String salt = StrUtils.getComplexRandomString(32);
        //通过和密码进行加密   加盐加密：
        String dbpassword = Md5Utils.encrypByMd5(salt + dto.getPassword());

        logininfo.setSalt(salt);

        logininfo.setPassword(dbpassword);

        return logininfo;
    }
}

